from rest_framework import serializers

from backend.utils.base_serializer import BaseSerializer, SerializerFactory
from backend.utils.custom_fields import CustomDateTimeField
from backend.utils.redis_utils import RedisUtils
from permissions.models import Meta, Menu, Role


class MetaModelSerializer(BaseSerializer):
    class Meta:
        fields = ['hideMenu', 'hideBreadcrumb', 'title', 'currentActiveMenu', 'icon', 'hideChildrenInMenu']
        model = Meta


class MenuModelSerializer(BaseSerializer):
    meta = MetaModelSerializer()

    class Meta:
        fields = ['path', 'name', 'component', 'meta']
        model = Menu


class MenuParentSerializer(MenuModelSerializer):
    children = MenuModelSerializer(many=True)

    class Meta:
        fields = ['path', 'name', 'component', 'meta', 'redirect', 'children']
        model = Menu


class MenuSerializer(BaseSerializer):
    icon = serializers.StringRelatedField(source='meta.icon', required=False)
    title = serializers.StringRelatedField(source='meta.title', required=False)
    create_time = CustomDateTimeField()

    class Meta:
        model = Menu
        fields = ['id', 'name', 'code', 'component', 'status', 'icon', 'title', 'create_time', 'type']


# class MenuTreeSerializer(BaseSerializer):
#     title = serializers.StringRelatedField(source='meta.title', required=False)
#
#     class Meta:
#         model = Menu
#         fields = ['id', 'name', 'title']


MenuTreeSerializer = SerializerFactory.build(Menu, fields=['id', 'name', 'title'],
                                             title=serializers.StringRelatedField(source='meta.title', required=False))


class MenuCreateSerializer(BaseSerializer):
    icon = serializers.CharField(source='meta.icon', required=False)
    title = serializers.CharField(source='meta.title', required=False)
    create_time = CustomDateTimeField()
    parent_id = serializers.IntegerField(required=False, allow_null=True)
    create_by = serializers.HiddenField(default=serializers.CurrentUserDefault())
    modified_by = serializers.HiddenField(default=serializers.CurrentUserDefault())

    class Meta:
        model = Menu
        fields = ['id', 'name', 'code', 'component', 'path', 'status', 'icon', 'title', 'create_time', 'type',
                  'parent_id',
                  'create_by', 'modified_by']

    def validate_parent_id(self, value):
        if value is None:
            return value
        try:
            Menu.advanced_objects.get(pk=value)
            return value
        except Exception as e:
            raise self.custom_validation_error("父级部门不存在")

    def validate(self, attrs):
        _id = self.request.data.get('id')
        parent_id = self.request.data.get('parent_id')
        if all([_id, parent_id]) and _id == parent_id:
            raise self.custom_validation_error('不能选择当前菜单作为自己的上级菜单')
        return super(MenuCreateSerializer, self).validate(attrs)

    def create(self, validated_data):
        meta = Meta.objects.create(**validated_data.pop('meta'))
        validated_data['meta_id'] = meta.id
        if validated_data.get('type') == 0:
            validated_data['component'] = 'LAYOUT'
        instance = Menu.objects.create(**validated_data)
        if self.user.roles.first():
            self.user.roles.first().menus.add(instance)
        RedisUtils('permission').delete(f'permission_code_{self.user.pk}')
        return instance

    def update(self, instance, validated_data):
        meta = validated_data.pop('meta')
        if validated_data.get('type') == 0:
            validated_data['component'] = 'LAYOUT'
        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        instance.save()
        for attr, value in meta.items():
            setattr(instance.meta, attr, value)
        instance.meta.save()
        return instance


# class RoleSerializer(BaseSerializer):
#     create_time = CustomDateTimeField()
#
#     class Meta:
#         model = Role
#         fields = ['id', 'name', 'remark', 'status', 'create_time']


RoleSerializer = SerializerFactory.build(Role, fields=['id', 'name', 'remark', 'status', 'create_time'],
                                         create_time=CustomDateTimeField())
